//
// Created by QU on 24-6-11.
//
#include <iostream>
#include <fstream>
#include <sstream>
#include <functional>
#include <utility>
#include <memory>
#include <vector>
#include <map>
#include <set>
#include <regex>

using std::cout, std::cin, std::endl, std::unitbuf;

int main(int argc, char const *argv[]) {
    // regex 表示一个正则表达式的类
    //regex_match 将一个字符符序列与一个正则表达式匹配
    //regex_search 找第 与正 表达式匹配的子序列

    /**
     * 如果整个输入序列与表达式匹配， regex_match 函数返回true
     * 如果输入序列中一个子串与表达式匹配， regex_search 函数返回true 。
     */

//    bool regex_search(const std::string& s, std::smatch& m, const std::regex& r, std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
//    bool regex_search(const std::string& s, const std::regex& r, std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
// 方便理解, 参数名称简写像下面这样.
//    bool regex_search( seq, m, r, flags = std::regex_constants::match_default);
//    bool regex_search( seq, r, flags = std::regex_constants::match_default);

/**
 * 在字符序列seq中查找regex对象r中的正则表达式。seq可以是个string、表示范围的一对迭代器以及一个指向空字符结尾的字符数组的指针
 *
 * m是一个match对象，用来保存匹配结果的相关细节。m和seq必须具有兼容的类型（参见17.3.1节，第649页）
 * flags是一个可选的regex_constants::match_flag_type值表17.13（第659页）描述了这些值，它们会影响匹配过程
 */

    // 定义模式，查找不以字符 'c' 开头的 "ei"
    std::string pattern = "[^c]ei";
    //////      aei  bei  fei  dei ....    反正不是cei.

    // 将模式扩展为包含整个单词
    pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
    //////      *任意多个字符, + 1个以上任意字符.

    // 构造一个用于查找模式的 regex 对象
    std::regex r(pattern);

    // 定义一个 smatch 对象保存搜索结果
    std::smatch results;

    // 定义一个字符串保存与模式匹配和不匹配的文本
    std::string test_str = "receipt freind theif receive aaaaeiaaa aaafei";

    // 用 regex_search 在 test_str 中查找与 pattern 匹配的子串, regex_search找到了就返回true, 不会进行后续的操作,
    // 如果想要得到全部的结果集, 后续会讲.
    if (std::regex_search(test_str, results, r)) {
        // 如果有匹配子串，打印匹配的单词
        std::cout << results.str() << std::endl;
    } else {
        // 如果没有匹配子串，打印没有匹配的提示
        std::cout << "No match found" << std::endl;
    }
    // 因为 "freind" 是符合条件的第一个单词。 返回的是friend,
    //regex_replace 使用给定格式替换 个正则表达式

    // std::smatch 是针对 std::string 类型的特化版本，提供了与字符串处理相关的特性。
    // 提供了方便的方法来获取匹配的子字符串和相关信息，例如 results.str() 返回整个匹配的字符串。

/**
        *    std::match_results 模板类有几个常用的特化类，用于不同类型的字符串匹配。以下是常用的几个特化类：
        *
        *    std::string 类型的匹配结果 。  std::regex std::smatch    std::ssub_match    std::sregex_iterator
        *    const char*）的匹配结果。     std::regex  std::cmatch    std::csub_match   std::cregex_iterator
        *    std::wstring）的匹配结果。    std::wregex  std::wsmatch  std::wssub_match  std::wsregex_iterator
        *    const wchar_t*）的匹配结果。  std::wregex  std::wcmatch  std::wssub_match  std::wsregex_iterator
*/

    // 任何其他程序设计语言一样，我们用这种语言编写的正则表达式也可能有错误。
    // regex_error
    /**
    *    正则表达式错误类型
    *    定义在regex和regex_constants::error_type中
    *    error_collate无效的元素校对请求
    *    error_ctype 无效的字符类
    *    error_escape 无效的转义字符或无效的尾置转义
    *    error_backref 无效的向后引用
    *    error_brack 不匹配的方括号 ([或])
    *    error_paren 不匹配的小括号 ((或)）
    *    error_brace 不匹配的花括号（{或}）
    *    error_badbrace {}中无效的范围
    *    error range 无效的字符范围（如[z-a])
    *    error_space 内存不足，无法处理此正则表达式
    *    error_badrepeat 重复字符（*、？、+或{）之前没有有效的正则表达式
    *    error_complexity 要求的匹配过于复杂
    *    error_stack 栈空间不足，无法处理匹配
    */

    //sregex_iterator 迭代器适配器，调用 regex_search 来遍历一个string中所有匹配的子串
    // 这些操作也适用于 cregex_iterator、 wsregex_iterator 和 wcregex_iterator。
    // sregex_iterator

    // sregex_iterator it(b,e,r);  一个sregex_iterator，遍历迭代器b和e表示的 string。
    //                                  它调用sregex_search（b，e，r）将it定位到输入中第一个匹配的位置
    // sregex_iterator it();      返回一个尾后迭代器.
    // *it / it->               返回一个smatch对象的引用或者一个指向一个smatch对象的指针.
    // ++it / it++              你猜...
    // it1 [== / !=] it2

    // 定义一个包含电子邮件地址的字符串
    std::string text = "Here are some emails: john.doe@example.com, jane.smith@company.org, info@website.net";

    // 定义一个正则表达式，用于匹配电子邮件地址
    std::regex email_pattern(R"(([[:alnum:].-]+)@([[:alnum:].-]+)\.([[:alpha:].]+))");

    // 创建一个 regex_iterator 对象
    auto begin = std::sregex_iterator(text.begin(), text.end(), email_pattern);
    auto end = std::sregex_iterator();

//    for (std::sregex_iterator it(text.cbegin(), text.cend(), email_pattern), end_it; it != end_it; ++it) {
//    }

    std::cout << "Found email addresses:" << std::endl;
//    std::match_results 对象中的 prefix() 和 suffix() 成员函数分别返回输入序列中当前匹配之前和之后的部分。
//    这两个函数返回的是 std::ssub_match 对象，它们用于提供有关匹配上下文的详细信息。


/**
 * 使用正则表达式迭代器（std::sregex_iterator）进行正则表达式匹配时，每个迭代器对象表示输入序列中一个匹配的结果。
 * 虽然你是通过迭代器逐个访问匹配结果，但实际上的匹配操作仍然是一次性完成的。
 * 换句话说，当你创建迭代器时，正则表达式引擎已经扫描了整个输入序列，并找出了所有匹配的子字符串。
 */
    for (auto i = begin; i != end; ++i) {
        std::smatch match = *i; // 解引用操作符，获取匹配结果
        if(!match.ready()){
            break;
        }

        // 获取匹配结果的前缀和后缀
        std::string prefix = match.prefix().str();
        // 可以利用length的返回值, 对循环做一些控制.
        auto prefix_length = match.prefix().length();

        std::string suffix = match.suffix().str();
        auto suffix_length = match.suffix().length();

        /**
         * prefix() 和 suffix() 的工作方式：
         *  prefix() 和 suffix() 是 std::match_results 类的成员函数，返回的是匹配结果之前和之后的子字符串。
         *  当你调用 prefix() 或 suffix() 时，这些方法不会进行新的搜索或计算，而是直接返回之前已经计算好的结果。
         */

        std::cout << "Match: " << match.str() << std::endl;
        std::cout << "Prefix: \"" << prefix << "\"" << "\t Length:" << prefix_length << std::endl;
        std::cout << "Suffix: \"" << suffix << "\"" << "\t Length:" << suffix_length << std::endl;
        std::cout << "------------------" << std::endl;
    }
    /*
     *  Found email addresses:
     *  Match: john.doe@example.com
     *  Prefix: "Here are some emails: "         Length:22
     *  Suffix: ", jane.smith@company.org, info@website.net"     Length:42
     *  ------------------
     *  Match: jane.smith@company.org
     *  Prefix: ", "     Length:2
     *  Suffix: ", info@website.net"     Length:18
     *  ------------------
     *  Match: info@website.net
     *  Prefix: ", "     Length:2
     *  Suffix: ""       Length:0
     *  ------------------
     *      第一条匹配项：
     *      Match: john.doe@example.com
     *      Prefix: "Here are some emails: "
     *      从字符串开始到 john.doe@example.com 之前的部分。
     *      Suffix: ", jane.smith@company.org, info@website.net"
     *      从 john.doe@example.com 之后到字符串结束的部分。
     *
     *      第二条匹配项：
     *      Match: jane.smith@company.org
     *      Prefix: ", john.doe@example.com"
     *      从前一个匹配项结束到 jane.smith@company.org 之前的部分。
     *      Suffix: ", info@website.net"
     *      从 jane.smith@company.org 之后到字符串结束的部分。
     *
     *      第三条匹配项：
     *      Match: info@website.net
     *      Prefix: ", john.doe@example.com, jane.smith@company.org"
     *      从前一个匹配项结束到 info@website.net 之前的部分。
     *      Suffix: ""
     *      info@website.net 之后没有任何字符，所以后缀为空。
     */

    //smatch 容器类，保存在string中搜索的结果
    //ssub_match 中匹配的子表达式的结果

    return 0;
}